/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 启用对处理用AspectJ的{@code @Aspect}注解标记的组件的支持。
 * 类似于Spring的{@code <aop:aspectj-autoproxy>}中的功能。
 * XML元素中的功能。
 * 要在@{@link Configuration}类上使用，如下所示
 *
 * <pre class="code">
 * &#064;Configuration
 * &#064;EnableAspectJAutoProxy
 * public class AppConfig {
 *
 *     &#064;Bean
 *     public FooService fooService() {
 *         return new FooService();
 *     }
 *
 *     &#064;Bean
 *     public MyAspect myAspect() {
 *         return new MyAspect();
 *     }
 * }</pre>
 *
 * Where {@code FooService} is a typical POJO component and {@code MyAspect} is an
 * {@code @Aspect}-style aspect:
 *
 * <pre class="code">
 * public class FooService {
 *
 *     // various methods
 * }</pre>
 *
 * <pre class="code">
 * &#064;Aspect
 * public class MyAspect {
 *
 *     &#064;Before("execution(* FooService+.*(..))")
 *     public void advice() {
 *         // advise FooService methods as appropriate
 *     }
 * }</pre>
 *
 *  在上面的场景中，{@code @EnableAspectJAutoProxy}确保了{@code MyAspect} 将被正确处理，并且{@code FooService}将被代理混合在一起。
 *  将被正确处理，并且{@code FooService}将被代理混合在它所贡献的它所提供的建议。
 *
 * 用户可以使用{@code FooService}来控制为{@code FooService}创建的代理的类型。
 * {@link #proxyTargetClass()}属性。
 * 下面的内容使CGLIB风格的 "子类 "成为可能。代理，而不是默认的基于接口的JDK代理方式。
 *
 * <pre class="code">
 * &#064;Configuration
 * &#064;EnableAspectJAutoProxy(proxyTargetClass=true)
 * public class AppConfig {
 *     // ...
 * }</pre>
 *
 * 请注意，{@code @Aspect}bean可以像其他bean一样进行组件扫描。
 * 只需用{@code @Aspect}和{@code @Component}标记该方面。
 *
 * <pre class="code">
 * package com.foo;
 *
 * &#064;Component
 * public class FooService { ... }
 *
 * &#064;Aspect
 * &#064;Component
 * public class MyAspect { ... }</pre>
 *
 * 然后使用@{@link ComponentScan}注解来选择这两者。
 *
 * <pre class="code">
 * &#064;Configuration
 * &#064;ComponentScan("com.foo")
 * &#064;EnableAspectJAutoProxy
 * public class AppConfig {
 *
 *     // no explicit &#064Bean definitions required
 * }</pre>
 *
 * 注意：{@code @EnableAspectJAutoProxy}仅适用于其本地应用环境。
 * 允许在不同层次上对Bean进行有选择的代理。
 * {@code @EnableAspectJAutoProxy}在每个单独的上下文中，
 * 例如共同的根Web应用上下文和任何单独的{@code DispatcherServlet}应用上下文中重新声明。
 * 如果你需要在多个层面上应用它的行为。
 *
 * 这个功能需要在classpath上存在{@code aspectjweaver}。
 * 虽然这个依赖对于{@code spring-aop}来说是可选的，但对于{@code @EnableAspectJAutoProxy}及其底层设施来说是必须的。
 * 对于{@code @EnableAspectJAutoProxy}和它的底层设施是必须的。
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see org.aspectj.lang.annotation.Aspect
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * 指示是否要创建基于子类（CGLIB）的代理，而不是基于标准Java接口的代理。
	 * 而不是基于标准Java接口的代理。默认是{@code false}。
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 表示代理应该被AOP框架作为{@code ThreadLocal}公开，以便通过{@link org.springframework.aop.framework.AopContext}类进行检索。
	 * 用于通过{@link org.springframework.aop.framework.AopContext}类进行检索。
	 * 默认情况下是关闭的，即不保证{@code AopContext}的访问会有效。
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}
